package chapter12.eg2;

import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.timeout.ReadTimeoutHandler;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

public class NettyClient {

  private ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);
  EventLoopGroup group = new NioEventLoopGroup();

  public void connect(int port, String host) throws InterruptedException {
    try {
      Bootstrap bootstrap = new Bootstrap();
      bootstrap.group(group)
        .channel(NioSocketChannel.class)
        .option(ChannelOption.TCP_NODELAY, true)
        .handler(new ChannelInitializer<SocketChannel>() {
          @Override
          protected void initChannel(SocketChannel ch) throws Exception {
            ch.pipeline().addLast(new NettyMessageDecoder());
            ch.pipeline().addLast("MessageEncoder", new NettyMessageEncoder());
            ch.pipeline().addLast("readTimeoutHandler", new ReadTimeoutHandler(50));
            ch.pipeline().addLast("LoginAuthHandler", new LoginAuthReqHandler());
            ch.pipeline().addLast("HeartBeatHandler", new HeartBeatReqHandler());
          }
        });

      ChannelFuture future = bootstrap.connect(host, port).sync();
      future.channel().closeFuture().sync();
    } finally {
      executor.execute(() -> {
        try {
          TimeUnit.SECONDS.sleep(5);
          try {
            connect(port, host);
          } catch (InterruptedException e) {
            e.printStackTrace();
          }
        } catch (InterruptedException e) {
          e.printStackTrace();
        }
      });
    }
  }

  public static void main(String[] args) throws InterruptedException {
    new NettyClient().connect(8080, "127.0.0.1");
  }

}
